/*
 * Matias Blanco & Sergio Perez
 * Pintores. Monitores en Java
 */

package pintoresmonitjava; 

import java.util.List;
import java.util.ArrayList;


class Sociedad{
    
    int MAX_BOTES = 4;
    int MAX_PINTORES = 8;
    int N_BOTES_COL = 2;
    
    boolean Suficientes;
    boolean PintoresEsperan[];
    boolean BotesRecibidosPint[];
    int Botes_Disponibles[];
    boolean PintBotesMat[][];
    
    public Sociedad(){
        Suficientes = true;
        PintoresEsperan = new boolean[MAX_PINTORES];
        BotesRecibidosPint = new boolean[MAX_PINTORES];
        Botes_Disponibles = new int[MAX_BOTES];
        PintBotesMat = new boolean[MAX_PINTORES][MAX_BOTES];
    
        for (int i=0;i<MAX_PINTORES;i++)
            PintoresEsperan[i] = false;
        for (int i=0;i<MAX_BOTES;i++){
            Botes_Disponibles[i] = N_BOTES_COL;
        } 
    }
    
	public synchronized boolean dame_botes(boolean botes [], int Id){
		
		System.out.println("(*P*) El pintor " + Id + " pide pedido botes...");
		Suficientes=true;
		for(int i=0; i< MAX_BOTES && Suficientes; i++) // en cuanto no se cumpla, salimos
			if(botes[i]==true &&Botes_Disponibles[i]==0)
				Suficientes=false;
		if(!Suficientes){
			PintoresEsperan[Id]=true;
			for(int i=0; i<MAX_BOTES; i++)
				PintBotesMat[Id][i]=botes[i];
			System.out.println("(*-*) En este momento no hay botes para " + Id);
		}
		
		else{
			for(int i=0;i<MAX_BOTES;i++)
				if(botes[i]==true)
					Botes_Disponibles[i]--;	
			System.out.println("(*OK*) El pintor "+ Id +" ya tiene sus botes.");
			
	    }
	    return Suficientes;			
	}
	
	public synchronized void devuelve_botes(boolean botes [], int Id){
		
		for(int i=0;i<MAX_BOTES;i++)
			if(botes[i]==true)
				Botes_Disponibles[i]++;
		System.out.println("(*De*) El pintor "+Id+" devuelve los botes.");
		repartir_botes();
		notifyAll ();
				
	}
	
	public synchronized void esperar_disponibles_botes(int id){
		try{
			while(!BotesRecibidosPint[id]) wait();
			BotesRecibidosPint[id] = false;
		}catch(Exception e){System.out.println("Error");}
				
	}
	
	public void repartir_botes (){
		for(int i=0;i<MAX_PINTORES;i++){
			if(PintoresEsperan[i]){
				Suficientes=true;
				for(int j=0;j<MAX_BOTES && Suficientes;j++)
					if(PintBotesMat[i][j] && Botes_Disponibles[j]==0)
							Suficientes=false;
				
				if(Suficientes){
					for(int j=0; j<MAX_BOTES;j++)
						if(PintBotesMat[i][j])
							Botes_Disponibles[j]--;
					PintoresEsperan[i]=false;
					System.out.println("(*Re*) El pintor "+i+" consigue sus botes en el reparto...");
					BotesRecibidosPint[i]=true;		
				}		
			}	
		}
	}        
    
}


class Cuadro{ // Una clase que representa cada cuadro
    int MAX_BOTES = 4;
    boolean Botes[];
    
    public Cuadro(){
        Botes = new boolean[MAX_BOTES];
    }
    
    public void set_Bote(int i, boolean st){
        Botes[i] = st;
    }
    
    public boolean[] get_Botes(){
        return Botes;
    }
    
}

class Pintor extends Thread{
	int MAX_CUADROS=5;
	int MAX_BOTES=4;
	int id;
	boolean BotesRecibidosPint;
	Cuadro cuadros [];
	Sociedad soc;
	
	public Pintor (int id, Sociedad soc){
		this.id=id;
		this.soc=soc;
		cuadros=new Cuadro[MAX_CUADROS];
		for(int i=0; i<MAX_CUADROS;i++){
			cuadros[i]=new Cuadro ();
			for(int j=0; j<MAX_BOTES;j++){
				double aleatorio=Math.random();
				if(aleatorio<0.5)
                                     cuadros[i].set_Bote(j,true);
                                else cuadros[i].set_Bote(j,false);
					
			}
		}
		
	}
	
	public void run(){
		try{
			for(int i=0; i<MAX_CUADROS;i++){
				System.out.println("-- El pintor "+id+" quiere pintar el cuadro "+i);
				BotesRecibidosPint = soc.dame_botes(cuadros[i].get_Botes (),id);
				if(!BotesRecibidosPint){
                	            	BotesRecibidosPint = false;
                                	soc.esperar_disponibles_botes(id);
				}
                                System.out.println("-- El pintor "+id+" empieza a pintar el cuadro "+i);
				Thread.sleep(3000+(int)Math.random()*7000);
				System.out.println("-- El pintor "+id+" termina de pintar el cuadro "+i);
				soc.devuelve_botes(cuadros[i].get_Botes (),id);
				Thread.sleep(2000);
	         }
                        System.out.println("-- (FIN) El pintor " + id + " ha pintado TODOS sus cuadros");
				
         }catch(Exception e){System.out.println("Error");}
	}
}	

class Main{
	public static void main(String [] args){
		
                int MAX_PINTORES = 8; 
                
                List lPintores = new ArrayList();
                Pintor tempPintor;
                
		try {
			System.out.println("Matias Blanco & Sergio Perez - Pintores Java Monitores\n\n");
			Sociedad Soc = new Sociedad();
                        
                        System.out.println("Lanzamos los pintores...\n");
			for(int i = 0; i < MAX_PINTORES; i++){
                            tempPintor = new Pintor(i,Soc);
                            tempPintor.start();
                            lPintores.add(tempPintor);
                            Thread.sleep(2000);
                        }                        
		}catch(Exception e){System.out.println("(*E*) Error");}
	}
}
